package com.dsbj.it.DingTalkBotStarter.service.impl;


import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsbj.it.DingTalkBotStarter.common.enums.FieldTypeEnum;
import com.dsbj.it.DingTalkBotStarter.dao.entity.DetailDO;
import com.dsbj.it.DingTalkBotStarter.dao.entity.HasDetail;
import com.dsbj.it.DingTalkBotStarter.dao.mapper.MyBaseMapper;
import com.dsbj.it.DingTalkBotStarter.util.ExcelListener;
import com.dsbj.it.DingTalkBotStarter.util.ExcelReader;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public abstract class AbstractExcelBatchSaveServiceImpl
        <Mapper extends MyBaseMapper<DO>, DO extends HasDetail>
        extends ServiceImpl<Mapper, DO> {

    protected static final Integer BATCH_LENGTH = 100;

    protected List<DO> batchSaveList = ListUtils.newArrayListWithExpectedSize(BATCH_LENGTH);

    /**
     * @Author: yancheng
     * @Date: 2025年8月22日
     * @Description: 核心处理方法(公用)
     */
    public void saveFromExcel() {
        ExcelListener parseListener = ExcelReader.df(getExcelFilePath());
        List<Map<Integer, Map<Integer, String>>> list = parseListener.getList();
        Map<Integer, String> headTitleMap = parseListener.getHeadTitleMap();
        Map<Integer, String> dynHeadTitleMap = parseListener.getDynHeadTitleMap();

        for (int i = 0; i < list.size(); i++) {
            Map<Integer, Map<Integer, String>> integerMapMap = list.get(i);
            integerMapMap.forEach((k, l) -> {
                DetailDO detailDO = DetailDO.builder()
                        .type(getDetailType())
                        .dynamic(new ArrayList<>())
                        .build();

                Map<String, String> dataMap = new LinkedHashMap<>();
                DO doEntity = createDO();
                setCommonProperties(doEntity, detailDO); // 设置detailDO到实体中

                // 现在可以安全调用getDetailDO()，因为DO实现了HasDetail接口
                l.forEach((y, z) -> {
                    dataMap.put(headTitleMap.get(y), z);
                    if (dynHeadTitleMap.keySet().contains(y)) {
                        doEntity.getDetailDO().getDynamic().add(z);
                    }
                });

                BeanUtil.copyProperties(dataMap, doEntity);
                batchSaveList.add(doEntity);
            });

            // 批量保存：现在getBaseMapper()返回的是MyBaseMapper类型，支持insertBatchSomeColumn
            if (batchSaveList.size() >= BATCH_LENGTH || i == list.size() - 1) {
                long start = System.currentTimeMillis();
                // 此处不再报错，因为Mapper泛型限定为MyBaseMapper
                int insertCount = getBaseMapper().insertBatchSomeColumn(batchSaveList);
                log.info("拟批量新增{}条 实际批量新增{}条", batchSaveList.size(), insertCount);
                log.info("总耗时：{} ms", System.currentTimeMillis() - start);
                batchSaveList = ListUtils.newArrayListWithExpectedSize(BATCH_LENGTH);
            }
        }
    }


    /**
     * 配置文件流
     */
    protected abstract String getExcelFilePath();

    /**
     * xxDO初始化
     */
    protected abstract DO createDO();

    /**
     * 配置对应数据类型
     */
    protected abstract FieldTypeEnum getDetailType();

    /**
     * 配置基本参数
     */
    protected abstract void setCommonProperties(DO doEntity, DetailDO detailDO);
}
